package ru.ifmo.network.skype.view.swing;

import ru.ifmo.network.skype.GroupProvider;
import ru.ifmo.network.skype.GroupsInfoListener;
import ru.ifmo.network.skype.UserData;
import ru.ifmo.network.skype.audio.UserListHandler;
import ru.ifmo.network.skype.audio.VolumeController;
import ru.ifmo.network.skype.network.GroupsController;
import ru.ifmo.network.skype.network.TCPClient;
import ru.ifmo.network.skype.network.data.Group;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;

import static ru.ifmo.network.SwingUtils.getBox;
import static ru.ifmo.network.SwingUtils.invokeLaterIfNotEDT;

/**
 * @author avhaliullin
 */
public class GUI extends JFrame implements UserListHandler, GroupsInfoListener {
    private final JTabbedPane tabbedPane = new JTabbedPane();
    private final ActiveItemsList<UserData> users;
    private final ActiveItemsList<UserData> others;
    private final Map<Long, ActiveItemsList<UserData>> groups = new HashMap<>();
    private final Map<UserData, Long> usersGroups = new HashMap<>();
    private final Map<Long, Group> groupsMap = new HashMap<>();
    private final GroupsController groupsController;
    private final ComponentProvider<UserData> componentProvider;
    private final TCPClient tcpClient;

    public GUI(final VolumeController volumeController, final GroupsController groupsController, final TCPClient tcpClient) {
        this.groupsController = groupsController;
        this.tcpClient = tcpClient;
        componentProvider = new ComponentProvider<UserData>() {
            @Override
            public JComponent getComponent(UserData data) {
                return new ListItemComponent(data, volumeController, tcpClient, new GroupProvider() {
                    @Override
                    public Group getGroup() {
                        return groupsController.getActiveGroup();
                    }
                });
            }
        };

        final JTextField groupName = new JTextField("My group");
        groupName.setMaximumSize(new Dimension(200, 25));
        final JButton createGroup = new JButton("Create group");
        createGroup.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                groupsController.addGroupInfo(new Group(System.currentTimeMillis(), groupName.getText()));
            }
        });

        users = new ActiveItemsList<UserData>(componentProvider);
        others = new ActiveItemsList<UserData>(componentProvider);
        invokeLaterIfNotEDT(new Runnable() {
            @Override
            public void run() {
                setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
                setSize(300, 800);
                getContentPane().add(getBox(true, getBox(false, groupName, createGroup), tabbedPane));
                JButton activation = new JButton("Connect");
                activation.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        groupsController.activate(null);
                    }
                });
                activation.setMaximumSize(activation.getPreferredSize());
                tabbedPane.add("MAIN", getBox(true, activation, users));
                tabbedPane.add("OTHERS", others);
            }
        });
    }

    @Override
    public void moveUser(UserData user, Long group) {
        Long userGroup = usersGroups.put(user, group);
        if ((userGroup == null && group != null) || (userGroup != null && !userGroup.equals(group))) {
            if (userGroup == null) {
                users.remove(user);
            } else {
                ActiveItemsList<UserData> list = groups.get(userGroup);
                if (list == null) {
                    others.remove(user);
                } else {
                    list.remove(user);
                }
            }
            if (group == null) {
                users.add(user);
            } else {
                ActiveItemsList<UserData> list = groups.get(group);
                if (list == null) {
                    others.add(user);
                } else {
                    list.add(user);
                }
            }
        }
    }

    @Override
    public void newUser(final UserData user) {
        invokeLaterIfNotEDT(new Runnable() {
            @Override
            public void run() {
                System.out.println("ADDING " + user.getName());
                users.add(user);
            }
        });
    }

    @Override
    public void removeUser(final UserData user) {
        invokeLaterIfNotEDT(new Runnable() {
            @Override
            public void run() {
                moveUser(user, null);
                users.remove(user);
            }
        });
    }

    @Override
    public void newGroup(final Group group) {
        groupsMap.put(group.getId(), group);
        JButton activation = new JButton("Connect");
        activation.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                groupsController.activate(group.getId());
            }
        });
        activation.setMaximumSize(activation.getPreferredSize());
        ActiveItemsList<UserData> list = new ActiveItemsList<UserData>(componentProvider);
        groups.put(group.getId(), list);
        tabbedPane.add(group.getName(), getBox(true, activation, list));
    }
}